#include <model.h>
string Setstr(const char * val){return val;}

Texture::Texture(const string &path,TextureType type){
	int pw,ph,nc;
    Type = type;
    stbi_set_flip_vertically_on_load(true);
	unsigned char *data=stbi_load(path.c_str(),&pw,&ph,&nc,0);
	glGenTextures(1,&ID);
	glBindTexture(GL_TEXTURE_2D,ID);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);   
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    GLint format = (nc==3?GL_RGB:GL_RGBA);
	glTexImage2D(GL_TEXTURE_2D,0,format,pw,ph,0,format,GL_UNSIGNED_BYTE,data);
	glGenerateMipmap(GL_TEXTURE_2D);
	stbi_image_free(data);
	glBindTexture(GL_TEXTURE_2D,0);
}

Mesh::Mesh(vector<Vertex> vertices, vector<unsigned int> indices, vector<Texture> textures){
    this->vertices = vertices;
    this->indices = indices;
    this->textures = textures;
    setupMesh();
}

void Mesh::setupMesh(){
    glGenVertexArrays(1,&VAO);
    glGenBuffers(1,&VBO);
    glGenBuffers(1,&EBO);
    
    glBindVertexArray(VAO);
    {
        glBindBuffer(GL_ARRAY_BUFFER,VBO);
        glBufferData(GL_ARRAY_BUFFER,vertices.size()*sizeof(Vertex),&vertices[0],GL_STATIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER,indices.size()*sizeof(unsigned int),&indices[0],GL_STATIC_DRAW);

        glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(Vertex),(void*)0);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof(Vertex),(void*)offsetof(Vertex,Normal));
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(2,2,GL_FLOAT,GL_FALSE,sizeof(Vertex),(void*)offsetof(Vertex,TexCoords));
        glEnableVertexAttribArray(2);

        glBindBuffer(GL_ARRAY_BUFFER,0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
    }
    glBindVertexArray(0);
}

void Mesh::Draw(Shader shader){
    unsigned int diffuseNr = 0;
    unsigned int specularNr = 0;
    unsigned int normalNr   = 0;
    unsigned int heightNr   = 0;
    for(unsigned int i = 0; i < textures.size(); i++)
    {
        // 获取纹理序号（diffuse_textureN 中的 N）
        string number;
        
        switch (textures[i].Type)
        {
            case Texture::texture_diffuse:
                number = std::to_string(diffuseNr++);
                break;
            case Texture::texture_specular:
                number = std::to_string(specularNr++);
                break;
            case Texture::texture_normal:
                number = std::to_string(normalNr++);
                break;
            case Texture::texture_height:
                number = std::to_string(heightNr++);
                break;
            default:
                break;
        }
        shader.setValue((enumtoStr(textures[i].Type) + number).c_str(), (int)i);
        textures[i].Use(i);
    }
    glActiveTexture(GL_TEXTURE0);

    // 绘制网格
    glBindVertexArray(VAO);
    glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);
}

void Texture::Use(unsigned int TextureID){
    glActiveTexture(GL_TEXTURE0 + TextureID);
    glBindTexture(GL_TEXTURE_2D,ID);
}